public class Player{
	private Token token;
	private String name;
	private int money = 15000000;
	private int position = 0;
	private int temporaryOrder;
	private int order = 1;
	private boolean isAlive = true;
	private int assignedLabel;
	private boolean isJailed = false;
	private boolean isBackwards = false;
	private int jailRoll = 0;
	private int totalSteps = 0;
	private boolean hasChestKey = false;
	private boolean hasChanceKey = false;
	private boolean utilityCursed = false;
	private boolean airportCursed = false;
	private boolean rollForDoublesCurse = false;
	private int extraTurn = 0;
	private int numberOfUtility = 0;
	private int numberOfAirport = 0;
	private int numberOfHouses = 0;
	private int numberOfHotels = 0;
	private boolean[] completedMonopoly = new boolean[8];

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//getters and setters//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public boolean[] getCompletedMonopoly() {
		return completedMonopoly;
	}
	public void setCompletedMonopoly(boolean[] completedMonopoly) {
		this.completedMonopoly = completedMonopoly;
	}
	public void setNumberOfAirport(int numberOfAirport) {
		this.numberOfAirport = numberOfAirport;
	}
	public int getNumberOfAirport() {
		return numberOfAirport;
	}
	public void setNumberOfUtility(int numberOfUtility) {
		this.numberOfUtility = numberOfUtility;
	}
	public int getNumberOfUtility() {
		return numberOfUtility;
	}
	public void setHasChanceKey(boolean hasChanceKey) {
		this.hasChanceKey = hasChanceKey;
	}
	public boolean hasChanceKey() {
		return hasChanceKey;
	}
	public void setHasChestKey(boolean hasChestKey) {
		this.hasChestKey = hasChestKey;
	}
	public boolean hasChestKey() {
		return hasChestKey;
	}
	public void setToken(Token token) {
		this.token = token;
	}
	public Token getToken() {
		return token;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setExtraTurn(int extraTurn) {
		this.extraTurn = extraTurn;
	}
	public int getExtraTurn() {
		return extraTurn;
	}
	public String getName() {
		return name;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	public int getMoney() {
		return money;
	}
	public void setPosition(int position) {
		this.position = position;
	}
	public int getPosition() {
		return position;
	}
	public void setAlive(boolean isAlive) {
		this.isAlive = isAlive;
	}
	public boolean isAlive() {
		return isAlive;
	}
	public void setOrder(int order) {
		this.order = order;
	}
	public int getOrder() {
		return order;
	}
	public void setAssignedLabel(int assignedLabel) {
		this.assignedLabel = assignedLabel;
	}
	public int getAssignedLabel() {
		return assignedLabel;
	}
	public void setTemporaryOrder(int temporaryOrder) {
		this.temporaryOrder = temporaryOrder;
	}
	public int getTemporaryOrder() {
		return temporaryOrder;
	}
	public void setJailed(boolean isJailed) {
		this.isJailed = isJailed;
	}
	public boolean isJailed() {
		return isJailed;
	}
	public void setJailRoll(int jailRoll) {
		this.jailRoll = jailRoll;
	}
	public int getJailRoll() {
		return jailRoll;
	}
	public void setTotalSteps(int totalSteps) {
		this.totalSteps = totalSteps;
	}
	public int getTotalSteps() {
		return totalSteps;
	}
	public void setBackwards(boolean isBackwards) {
		this.isBackwards = isBackwards;
	}
	public boolean isBackwards() {
		return isBackwards;
	}
	public void setRollForDoublesCurse(boolean rollForDoublesCurse) {
		this.rollForDoublesCurse = rollForDoublesCurse;
	}
	public boolean isRollForDoublesCurse() {
		return rollForDoublesCurse;
	}
	
	public void setUtilityCursed(boolean utilityCursed) {
		this.utilityCursed = utilityCursed;
	}
	public boolean isUtilityCursed() {
		return utilityCursed;
	}
	public void setAirportCursed(boolean airportCursed) {
		this.airportCursed = airportCursed;
	}
	public boolean isAirportCursed() {
		return airportCursed;
	}


	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public Player createPlayer(String name){ //function for creating player. returns the created player
		Player player = new Player();
		player.token = new Token();
		player.setName(name);
		for(int k=0;k<=7;k++){
			player.completedMonopoly[k] = false;
		}
		return player;
	}
	
	public void updateCompletedMonopoly(Board board, int counter){
		//VIOLET
		if(counter==board.getBlock()[1].getEstate().getOwnerInt()
				&&counter==board.getBlock()[3].getEstate().getOwnerInt())
			completedMonopoly[0] = true;
		else
			completedMonopoly[0] = false;
		//WHITE
		if(counter==board.getBlock()[6].getEstate().getOwnerInt()
				&&counter==board.getBlock()[8].getEstate().getOwnerInt()
				&&counter==board.getBlock()[9].getEstate().getOwnerInt())
			completedMonopoly[1] = true;
		else
			completedMonopoly[1] = false;
		//PINK
		if(counter==board.getBlock()[11].getEstate().getOwnerInt()
				&&counter==board.getBlock()[13].getEstate().getOwnerInt()
				&&counter==board.getBlock()[14].getEstate().getOwnerInt())
			completedMonopoly[2] = true;
		else
			completedMonopoly[2] = false;
		//ORANGE
		if(counter==board.getBlock()[16].getEstate().getOwnerInt()
				&&counter==board.getBlock()[18].getEstate().getOwnerInt()
				&&counter==board.getBlock()[19].getEstate().getOwnerInt())
			completedMonopoly[3] = true;
		else
			completedMonopoly[3] = false;
		//RED
		if(counter==board.getBlock()[21].getEstate().getOwnerInt()
				&&counter==board.getBlock()[23].getEstate().getOwnerInt()
				&&counter==board.getBlock()[24].getEstate().getOwnerInt())
			completedMonopoly[4] = true;
		else
			completedMonopoly[4] = false;
		//YELLOW
		if(counter==board.getBlock()[26].getEstate().getOwnerInt()
				&&counter==board.getBlock()[27].getEstate().getOwnerInt()
				&&counter==board.getBlock()[29].getEstate().getOwnerInt())
			completedMonopoly[5] = true;
		else
			completedMonopoly[5] = false;
		//GREEN
		if(counter==board.getBlock()[31].getEstate().getOwnerInt()
				&&counter==board.getBlock()[32].getEstate().getOwnerInt()
				&&counter==board.getBlock()[34].getEstate().getOwnerInt())
			completedMonopoly[6] = true;
		else
			completedMonopoly[6] = false;
		//BLUE
		if(counter==board.getBlock()[37].getEstate().getOwnerInt()
				&&counter==board.getBlock()[39].getEstate().getOwnerInt())
			completedMonopoly[7] = true;
		else
			completedMonopoly[7] = false;
	}
	
	public void buyProperty(Block block, Player[] orderedPlayer, int counter, Board board){
		switch(block.getType()){
		case 1:
			addOwnership(block.getEstate(), orderedPlayer, counter);
			orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() - block.getEstate().getPrice());
			updateCompletedMonopoly(board, counter);
			break;
		case 2:
			addOwnership(block.getAirport(), orderedPlayer, counter);
			numberOfAirport+=1;
			orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() - block.getAirport().getPrice());
			break;
		case 3:
			addOwnership(block.getUtility(), orderedPlayer, counter);
			numberOfUtility+=1;
			orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() - block.getUtility().getPrice());
			break;
		}
	}
	
	public void addOwnership(Property property, Player [] orderedPlayer, int counter){
		//A function that simply adds the buyers name and corresponding integer into the property bought
		property.setOwned(true);
		property.setOwner(orderedPlayer[counter].getName());
		property.setOwnerInt(counter);
	}
	
	public int computeForRent(Block[] block, int position, Player[] orderedPlayer, int counter, int diceResult1, int diceResult2){
		//A function that computes for the rent that should be payed by a player. A switch is created to handle the different
		//types of computation with regards to airport, estate, and utility.
		int rent = 0;	//indicates the amount to be payed. This variable will be changed later on.
		int owner = 0;	//the integer representation of the player. 
		int typeOfRent = 0;	//a variable that will be changed and used to determine which type of rent (according to titleDeed class)
		//will be used. 0 is the default type and refers to the normal rent. (See titleDeed.java)
		switch(block[orderedPlayer[counter].getPosition()].getType()){
		case 1://Estates
			typeOfRent = block[position].getEstate().getNumberOfHouse();	//type of rent depends on the number of houses
			owner = block[orderedPlayer[counter].getPosition()].getEstate().getOwnerInt();
			rent = block[position].getEstate().getTitleDeed().getRentEstate()[typeOfRent];//the rent is computed here
			if(orderedPlayer[owner].completedMonopoly[block[position].getEstate().getColorGroup()] && block[position].getEstate().getNumberOfHouse()==0){
				//if a owner has completed a colour group and that property isn't developed yet. the rent is doubled
				rent = rent*2;
				}
			break;
			
		case 2:	//airport
			owner = block[orderedPlayer[counter].getPosition()].getAirport().getOwnerInt();
			typeOfRent = orderedPlayer[owner].getNumberOfAirport()-1;	//typeOfRent depends on the number of airports owned
			//by getting the size of the airportList minus 1 because the normal rent is 0 which corresponds to 1 airport.
			if(isAirportCursed()){ //when player draws chance card number 12 or 13
				rent = (block[position].getAirport().getTitleDeed().getRentAirport()[typeOfRent])*2;
				setAirportCursed(false);	//removes the curse placed on the player caused by chance
			}
			else{//otherwise, if not cursed, normal rent
				rent = block[position].getAirport().getTitleDeed().getRentAirport()[typeOfRent];
			}
			break;
			
		case 3://utility
			owner = block[orderedPlayer[counter].getPosition()].getUtility().getOwnerInt();
			if(isUtilityCursed()){ //when player draws chance card number 11
				rent = (100000*(diceResult1+diceResult2));
				setUtilityCursed(false);
			}
			else{
				typeOfRent = orderedPlayer[owner].getNumberOfUtility()-1;  //type of rent depends on the number of utilities owned -1 since
				//the normal rent would be 0 which refers to 1 utility owned
				rent = (block[position].getUtility().getTitleDeed().getRentUtility()[typeOfRent])*(diceResult1+diceResult2);
				//rent depends on the number of utilities times the result of dice1 and dice2
			}
			break;
		}
		return rent;	//returns the rent computed since only 1 case would be active during a function use
	}
	
	public void payRent(Player[] orderedPlayer, int counter, int rent, Block[] block){
		//A function that would allow a player to pay rent to the property's owner
		int owner = 0;
		switch(block[orderedPlayer[counter].getPosition()].getType()){//switch that gets the integer value of owner
		case 1:
			owner = block[orderedPlayer[counter].getPosition()].getEstate().getOwnerInt();
			break;
		case 2:
			owner = block[orderedPlayer[counter].getPosition()].getAirport().getOwnerInt();
			break;
		case 3:
			owner = block[orderedPlayer[counter].getPosition()].getUtility().getOwnerInt();
			break;
		}
		
		orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() - rent);	//rent is deducted from the current player
		orderedPlayer[owner].setMoney(orderedPlayer[owner].getMoney() + rent);	//rent is added to the owner
	}
	
	public void goToJail(Player[] orderedPlayer, int counter){
		//A function that places a player on jail by setting its position on jail.
		//extraTurn is reset because if you happen to acquire a double dice upon landing on tile 30.
		orderedPlayer[counter].setExtraTurn(0); //extra turns reset when player gets jailed
		orderedPlayer[counter].setPosition(10);
	}
	
	public void buyHouse(Block[] block, Player[] orderedPlayer, int counter, int tileClicked){
		//A function that increments the number of house on a property that you own and deducts your money according
		//to the houseCost as stated on the titleDeed class
		//tileClicked is used to determine the location of the block click during buying houses
		block[tileClicked].getEstate().setNumberOfHouse(block[tileClicked].getEstate().getNumberOfHouse() + 1);
		int houseCost = block[tileClicked].getEstate().getTitleDeed().getHouseCost();
		orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() - houseCost);
		
		if(block[tileClicked].getEstate().getNumberOfHouse()==5){
			orderedPlayer[counter].setNumberOfHouses(orderedPlayer[counter].getNumberOfHouses()-4);
			orderedPlayer[counter].setNumberOfHotels(orderedPlayer[counter].getNumberOfHotels()+1);
		}else
			orderedPlayer[counter].setNumberOfHouses(orderedPlayer[counter].getNumberOfHouses()+1);

		//System.out.println("HOUSES : "+numberOfHouses);
		//System.out.println("HOTELS : "+numberOfHotels);
	}
	
	public void sellHouse(Block[] block, Player[] orderedPlayer, int counter, int tileClicked){
		if(block[tileClicked].getEstate().getNumberOfHouse()==5){
			orderedPlayer[counter].setNumberOfHouses(orderedPlayer[counter].getNumberOfHouses()+4);
			orderedPlayer[counter].setNumberOfHotels(orderedPlayer[counter].getNumberOfHotels()-1);
		}else
			orderedPlayer[counter].setNumberOfHouses(orderedPlayer[counter].getNumberOfHouses()-1);
		
		block[tileClicked].getEstate().setNumberOfHouse(block[tileClicked].getEstate().getNumberOfHouse() - 1);
		int moneyEarned = (block[tileClicked].getEstate().getTitleDeed().getHouseCost())/2;
		orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() + moneyEarned);
		
		//System.out.println("HOUSES : "+numberOfHouses);
		//System.out.println("HOTELS : "+numberOfHotels);
	}

	public void mortgageProperty(Player[] orderedPlayer, int counter, Block[] block, int tileClicked){
		int mortgagePrice = 0;
		
		switch(block[tileClicked].getType()){
			case 1:
				block[tileClicked].getEstate().setMortgaged(true);
				mortgagePrice = block[tileClicked].getEstate().getTitleDeed().getMortgageValue();
				break;
			case 2:
				block[tileClicked].getAirport().setMortgaged(true);
				mortgagePrice = block[tileClicked].getAirport().getTitleDeed().getMortgageValue();
				break;
			case 3:
				block[tileClicked].getUtility().setMortgaged(true);
				mortgagePrice = block[tileClicked].getUtility().getTitleDeed().getMortgageValue();
				break;
		}
		
		orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() + mortgagePrice);
	}
	
	public void redeemProperty(Player[] orderedPlayer, int counter, Block[] block, int tileClicked){
		int redeemPrice = 0;
		
		switch(block[tileClicked].getType()){
			case 1:
				block[tileClicked].getEstate().setMortgaged(false);
				redeemPrice = block[tileClicked].getEstate().getTitleDeed().getRedeemValue();
				break;
			case 2:
				block[tileClicked].getAirport().setMortgaged(false);
				redeemPrice = block[tileClicked].getAirport().getTitleDeed().getRedeemValue();
				break;
			case 3:
				block[tileClicked].getUtility().setMortgaged(false);
				redeemPrice = block[tileClicked].getUtility().getTitleDeed().getRedeemValue();
				break;
		}
		
		orderedPlayer[counter].setMoney(orderedPlayer[counter].getMoney() - redeemPrice);
	}

	//this function will update the player's number of airport/utility and his/her colour group list
	public void updatePropertyStatus(Board board, Block[] block, int counter){
		//FOR MONOPOLY
			updateCompletedMonopoly(board, counter);
		//FOR NUMBER OF AIRPORT
			numberOfAirport=0;
			if(counter==block[5].getAirport().getOwnerInt())
				numberOfAirport+=1;
			if(counter==block[15].getAirport().getOwnerInt())
				numberOfAirport+=1;
			if(counter==block[25].getAirport().getOwnerInt())
				numberOfAirport+=1;
			if(counter==block[35].getAirport().getOwnerInt())
				numberOfAirport+=1;
		//FOR NUMBER OF UTILITY
			numberOfUtility=0;
			if(counter==block[12].getUtility().getOwnerInt())
				numberOfUtility+=1;
			if(counter==block[28].getUtility().getOwnerInt())
				numberOfUtility+=1;
	}
	
	public void surrender(Board board, int counter){
		this.isAlive = false;
		this.setMoney(0);
		releaseAllProperty(board, counter);
		if(this.hasChanceKey){
			board.getBlock()[7].getChance().setKeyUsed(false);
			board.getBlock()[22].getChance().setKeyUsed(false);
			board.getBlock()[36].getChance().setKeyUsed(false);
		}
		if(this.hasChestKey){
			board.getBlock()[2].getChest().setKeyUsed(false);
			board.getBlock()[17].getChest().setKeyUsed(false);
			board.getBlock()[33].getChest().setKeyUsed(false);
		}
	}
	
	public void releaseAllProperty(Board board, int counter){
		for(int x=0;x<40;x++){
			if(board.getBlock()[x].getType() == 1){
				if(board.getBlock()[x].getEstate().getOwnerInt() == counter){
					board.getBlock()[x].getEstate().setOwnerInt(-1);
					board.getBlock()[x].getEstate().setOwned(false);
					board.getBlock()[x].getEstate().setOwner(null);
					board.getBlock()[x].getEstate().setMortgaged(false);
					board.getBlock()[x].getEstate().setNumberOfHouse(0);
					board.getBlock()[x].getEstate().setCanHaveHouse(false);
					board.getBlock()[x].getEstate().setCanLoseHouse(false);
				}
			}
			
			if(board.getBlock()[x].getType() == 2){
				if(board.getBlock()[x].getAirport().getOwnerInt() == counter){
					board.getBlock()[x].getAirport().setOwnerInt(-1);
					board.getBlock()[x].getAirport().setOwned(false);
					board.getBlock()[x].getAirport().setOwner(null);
					board.getBlock()[x].getAirport().setMortgaged(false);
				}
			}
			
			if(board.getBlock()[x].getType() == 3){
				if(board.getBlock()[x].getUtility().getOwnerInt() == counter){
					board.getBlock()[x].getUtility().setOwnerInt(-1);
					board.getBlock()[x].getUtility().setOwned(false);
					board.getBlock()[x].getUtility().setOwner(null);
					board.getBlock()[x].getUtility().setMortgaged(false);
				}
			}
		}
	}
	
	public boolean checkMoney(int bid){
		boolean isMoneyValid = true;
		bid+=100000;
		if(money<bid){
			isMoneyValid = false;
		}
		return isMoneyValid;
	}
	
	public boolean checkMoneyOnAccept(int bid){
		boolean isMoneyValid = true;
		if(money<bid){
			isMoneyValid = false;
		}
		return isMoneyValid;
	}
	
	
	public void setNumberOfHouses(int numberOfHouses) {
		this.numberOfHouses = numberOfHouses;
	}
	public int getNumberOfHouses() {
		return numberOfHouses;
	}
	public void setNumberOfHotels(int numberOfHotels) {
		this.numberOfHotels = numberOfHotels;
	}
	public int getNumberOfHotels() {
		return numberOfHotels;
	}

}
